home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / cspike10.zip / WEAPONS.QC < prev   
Text File  |  1996-09-03  |  26KB  |  1,246 lines

  1. // NOTE that all patches from original weapons.qc are deliniated 
  2. // by PATCH and ENDPATCH comments.  Remove all between and your back
  3. // to square one.
  4.  
  5. //PATCH***********************************************
  6. // spikes.qc quake c EXTERNALS
  7. //****************************************************
  8. void () NewGrenadeExplode;
  9. void () new_spike_touch;
  10. void () new_superspike_touch;
  11. //ENDPATCH********************************************
  12.  
  13. /*
  14. */
  15. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  16. void () player_run;
  17. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  18. void(vector org, vector vel, float damage) SpawnBlood;
  19. void() SuperDamageSound;
  20.  
  21.  
  22. // called by worldspawn
  23. void() W_Precache =
  24. {
  25.     precache_sound ("weapons/r_exp3.wav");    // new rocket explosion
  26.     precache_sound ("weapons/rocket1i.wav");    // spike gun
  27.     precache_sound ("weapons/sgun1.wav");
  28.     precache_sound ("weapons/guncock.wav");    // player shotgun
  29.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  30.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  31.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  32.     precache_sound ("weapons/spike2.wav");    // super spikes
  33.     precache_sound ("weapons/tink1.wav");    // spikes tink (used in c code)
  34.     precache_sound ("weapons/grenade.wav");    // grenade launcher
  35.     precache_sound ("weapons/bounce.wav");        // grenade bounce
  36.     precache_sound ("weapons/shotgn2.wav");    // super shotgun
  37. };
  38.  
  39. float() crandom =
  40. {
  41.     return 2*(random() - 0.5);
  42. };
  43.  
  44. /*
  45. ================
  46. W_FireAxe
  47. ================
  48. */
  49. void() W_FireAxe =
  50. {
  51.     local    vector    source;
  52.     local    vector    org;
  53.  
  54.     source = self.origin + '0 0 16';
  55.     traceline (source, source + v_forward*64, FALSE, self);
  56.     if (trace_fraction == 1.0)
  57.         return;
  58.     
  59.     org = trace_endpos - v_forward*4;
  60.  
  61.     if (trace_ent.takedamage)
  62.     {
  63.         trace_ent.axhitme = 1;
  64.         SpawnBlood (org, '0 0 0', 20);
  65.         T_Damage (trace_ent, self, self, 20);
  66.     }
  67.     else
  68.     {    // hit wall
  69.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  70.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  71.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  72.         WriteCoord (MSG_BROADCAST, org_x);
  73.         WriteCoord (MSG_BROADCAST, org_y);
  74.         WriteCoord (MSG_BROADCAST, org_z);
  75.     }
  76. };
  77.  
  78.  
  79. //============================================================================
  80.  
  81.  
  82. vector() wall_velocity =
  83. {
  84.     local vector    vel;
  85.     
  86.     vel = normalize (self.velocity);
  87.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  88.     vel = vel + 2*trace_plane_normal;
  89.     vel = vel * 200;
  90.     
  91.     return vel;
  92. };
  93.  
  94.  
  95. /*
  96. ================
  97. SpawnMeatSpray
  98. ================
  99. */
  100. void(vector org, vector vel) SpawnMeatSpray =
  101. {
  102.     local    entity missile, mpuff;
  103.     local    vector    org;
  104.  
  105.     missile = spawn ();
  106.     missile.owner = self;
  107.     missile.movetype = MOVETYPE_BOUNCE;
  108.     missile.solid = SOLID_NOT;
  109.  
  110.     makevectors (self.angles);
  111.  
  112.     missile.velocity = vel;
  113.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  114.  
  115.     missile.avelocity = '3000 1000 2000';
  116.     
  117. // set missile duration
  118.     missile.nextthink = time + 1;
  119.     missile.think = SUB_Remove;
  120.  
  121.     setmodel (missile, "progs/zom_gib.mdl");
  122.     setsize (missile, '0 0 0', '0 0 0');        
  123.     setorigin (missile, org);
  124. };
  125.  
  126. /*
  127. ================
  128. SpawnBlood
  129. ================
  130. */
  131. void(vector org, vector vel, float damage) SpawnBlood =
  132. {
  133.     particle (org, vel*0.1, 73, damage*2);
  134. };
  135.  
  136. /*
  137. ================
  138. spawn_touchblood
  139. ================
  140. */
  141. void(float damage) spawn_touchblood =
  142. {
  143.     local vector    vel;
  144.  
  145.     vel = wall_velocity () * 0.2;
  146.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  147. };
  148.  
  149.  
  150. /*
  151. ================
  152. SpawnChunk
  153. ================
  154. */
  155. void(vector org, vector vel) SpawnChunk =
  156. {
  157.     particle (org, vel*0.02, 0, 10);
  158. };
  159.  
  160. /*
  161. ==============================================================================
  162.  
  163. MULTI-DAMAGE
  164.  
  165. Collects multiple small damages into a single damage
  166.  
  167. ==============================================================================
  168. */
  169.  
  170. entity    multi_ent;
  171. float    multi_damage;
  172.  
  173. void() ClearMultiDamage =
  174. {
  175.     multi_ent = world;
  176.     multi_damage = 0;
  177. };
  178.  
  179. void() ApplyMultiDamage =
  180. {
  181.     if (!multi_ent)
  182.         return;
  183.     T_Damage (multi_ent, self, self, multi_damage);
  184. };
  185.  
  186. void(entity hit, float damage) AddMultiDamage =
  187. {
  188.     if (!hit)
  189.         return;
  190.     
  191.     if (hit != multi_ent)
  192.     {
  193.         ApplyMultiDamage ();
  194.         multi_damage = damage;
  195.         multi_ent = hit;
  196.     }
  197.     else
  198.         multi_damage = multi_damage + damage;
  199. };
  200.  
  201. /*
  202. ==============================================================================
  203.  
  204. BULLETS
  205.  
  206. ==============================================================================
  207. */
  208.  
  209. /*
  210. ================
  211. TraceAttack
  212. ================
  213. */
  214. void(float damage, vector dir) TraceAttack =
  215. {
  216.     local    vector    vel, org;
  217.     
  218.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  219.     vel = vel + 2*trace_plane_normal;
  220.     vel = vel * 200;
  221.  
  222.     org = trace_endpos - dir*4;
  223.  
  224.     if (trace_ent.takedamage)
  225.     {
  226.         SpawnBlood (org, vel*0.2, damage);
  227.         AddMultiDamage (trace_ent, damage);
  228.     }
  229.     else
  230.     {
  231.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  232.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  233.         WriteCoord (MSG_BROADCAST, org_x);
  234.         WriteCoord (MSG_BROADCAST, org_y);
  235.         WriteCoord (MSG_BROADCAST, org_z);
  236.     }
  237. };
  238.  
  239. /*
  240. ================
  241. FireBullets
  242.  
  243. Used by shotgun, super shotgun, and enemy soldier firing
  244. Go to the trouble of combining multiple pellets into a single damage call.
  245. ================
  246. */
  247. void(float shotcount, vector dir, vector spread) FireBullets =
  248. {
  249.     local    vector direction;
  250.     local    vector    src;
  251.     
  252.     makevectors(self.v_angle);
  253.  
  254.     src = self.origin + v_forward*10;
  255.     src_z = self.absmin_z + self.size_z * 0.7;
  256.  
  257.     ClearMultiDamage ();
  258.     while (shotcount > 0)
  259.     {
  260.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  261.  
  262.         traceline (src, src + direction*2048, FALSE, self);
  263.         if (trace_fraction != 1.0)
  264.             TraceAttack (4, direction);
  265.  
  266.         shotcount = shotcount - 1;
  267.     }
  268.     ApplyMultiDamage ();
  269. };
  270.  
  271. /*
  272. ================
  273. W_FireShotgun
  274. ================
  275. */
  276. void() W_FireShotgun =
  277. {
  278.     local vector dir;
  279.  
  280.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  281.  
  282.     self.punchangle_x = -2;
  283.     
  284.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  285.     dir = aim (self, 100000);
  286.     FireBullets (6, dir, '0.04 0.04 0');
  287. };
  288.  
  289.  
  290. /*
  291. ================
  292. W_FireSuperShotgun
  293. ================
  294. */
  295. void() W_FireSuperShotgun =
  296. {
  297.     local vector dir;
  298.  
  299.     if (self.currentammo == 1)
  300.     {
  301.         W_FireShotgun ();
  302.         return;
  303.     }
  304.         
  305.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  306.  
  307.     self.punchangle_x = -4;
  308.     
  309.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  310.     dir = aim (self, 100000);
  311.     FireBullets (14, dir, '0.14 0.08 0');
  312. };
  313.  
  314.  
  315. /*
  316. ==============================================================================
  317.  
  318. ROCKETS
  319.  
  320. ==============================================================================
  321. */
  322.  
  323. void()    s_explode1    =    [0,        s_explode2] {};
  324. void()    s_explode2    =    [1,        s_explode3] {};
  325. void()    s_explode3    =    [2,        s_explode4] {};
  326. void()    s_explode4    =    [3,        s_explode5] {};
  327. void()    s_explode5    =    [4,        s_explode6] {};
  328. void()    s_explode6    =    [5,        SUB_Remove] {};
  329.  
  330. void() BecomeExplosion =
  331. {
  332.     self.movetype = MOVETYPE_NONE;
  333.     self.velocity = '0 0 0';
  334.     self.touch = SUB_Null;
  335.     setmodel (self, "progs/s_explod.spr");
  336.     self.solid = SOLID_NOT;
  337.     s_explode1 ();
  338. };
  339.  
  340. void() T_MissileTouch =
  341. {
  342.     local float    damg;
  343.  
  344.     if (other == self.owner)
  345.         return;        // don't explode on owner
  346.  
  347.     if (pointcontents(self.origin) == CONTENT_SKY)
  348.     {
  349.         remove(self);
  350.         return;
  351.     }
  352.  
  353.     damg = 100 + random()*20;
  354.     
  355.     if (other.health)
  356.     {
  357.         if (other.classname == "monster_shambler")
  358.             damg = damg * 0.5;    // mostly immune
  359.         T_Damage (other, self, self.owner, damg );
  360.     }
  361.  
  362.     // don't do radius damage to the other, because all the damage
  363.     // was done in the impact
  364.     T_RadiusDamage (self, self.owner, 120, other);
  365.  
  366. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  367.     self.origin = self.origin - 8*normalize(self.velocity);
  368.  
  369.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  370.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  371.     WriteCoord (MSG_BROADCAST, self.origin_x);
  372.     WriteCoord (MSG_BROADCAST, self.origin_y);
  373.     WriteCoord (MSG_BROADCAST, self.origin_z);
  374.  
  375.     BecomeExplosion ();
  376. };
  377.  
  378.  
  379.  
  380. /*
  381. ================
  382. W_FireRocket
  383. ================
  384. */
  385. void() W_FireRocket =
  386. {
  387.     local    entity missile, mpuff;
  388.     
  389.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  390.     
  391.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  392.  
  393.     self.punchangle_x = -2;
  394.  
  395.     missile = spawn ();
  396.     missile.owner = self;
  397.     missile.movetype = MOVETYPE_FLYMISSILE;
  398.     missile.solid = SOLID_BBOX;
  399.         
  400. // set missile speed    
  401.  
  402.     makevectors (self.v_angle);
  403.     missile.velocity = aim(self, 1000);
  404.     missile.velocity = missile.velocity * 1000;
  405.     missile.angles = vectoangles(missile.velocity);
  406.     
  407.     missile.touch = T_MissileTouch;
  408.     
  409. // set missile duration
  410.     missile.nextthink = time + 5;
  411.     missile.think = SUB_Remove;
  412.  
  413.     setmodel (missile, "progs/missile.mdl");
  414.     setsize (missile, '0 0 0', '0 0 0');        
  415.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  416. };
  417.  
  418. /*
  419. ===============================================================================
  420.  
  421. LIGHTNING
  422.  
  423. ===============================================================================
  424. */
  425.  
  426. /*
  427. =================
  428. LightningDamage
  429. =================
  430. */
  431. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  432. {
  433.     local entity        e1, e2;
  434.     local vector        f;
  435.     
  436.     f = p2 - p1;
  437.     normalize (f);
  438.     f_x = 0 - f_y;
  439.     f_y = f_x;
  440.     f_z = 0;
  441.     f = f*16;
  442.  
  443.     e1 = e2 = world;
  444.  
  445.     traceline (p1, p2, FALSE, self);
  446.     if (trace_ent.takedamage)
  447.     {
  448.         particle (trace_endpos, '0 0 100', 225, damage*4);
  449.         T_Damage (trace_ent, from, from, damage);
  450.         if (self.classname == "player")
  451.         {
  452.             if (other.classname == "player")
  453.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  454.         }
  455.     }
  456.     e1 = trace_ent;
  457.  
  458.     traceline (p1 + f, p2 + f, FALSE, self);
  459.     if (trace_ent != e1 && trace_ent.takedamage)
  460.     {
  461.         particle (trace_endpos, '0 0 100', 225, damage*4);
  462.         T_Damage (trace_ent, from, from, damage);
  463.     }
  464.     e2 = trace_ent;
  465.  
  466.     traceline (p1 - f, p2 - f, FALSE, self);
  467.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  468.     {
  469.         particle (trace_endpos, '0 0 100', 225, damage*4);
  470.         T_Damage (trace_ent, from, from, damage);
  471.     }
  472. };
  473.  
  474.  
  475. void() W_FireLightning =
  476. {
  477.     local    vector        org;
  478.  
  479.     if (self.ammo_cells < 1)
  480.     {
  481.         self.weapon = W_BestWeapon ();
  482.         W_SetCurrentAmmo ();
  483.         return;
  484.     }
  485.  
  486. // explode if under water
  487.     if (self.waterlevel > 1)
  488.     {
  489.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  490.         self.ammo_cells = 0;
  491.         W_SetCurrentAmmo ();
  492.         return;
  493.     }
  494.  
  495.     if (self.t_width < time)
  496.     {
  497.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  498.         self.t_width = time + 0.6;
  499.     }
  500.     self.punchangle_x = -2;
  501.  
  502.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  503.  
  504.     org = self.origin + '0 0 16';
  505.     
  506.     traceline (org, org + v_forward*600, TRUE, self);
  507.  
  508.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  509.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  510.     WriteEntity (MSG_BROADCAST, self);
  511.     WriteCoord (MSG_BROADCAST, org_x);
  512.     WriteCoord (MSG_BROADCAST, org_y);
  513.     WriteCoord (MSG_BROADCAST, org_z);
  514.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  515.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  516.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  517.  
  518.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  519. };
  520.  
  521.  
  522. //=============================================================================
  523.  
  524.  
  525. void() GrenadeExplode =
  526. {
  527.     T_RadiusDamage (self, self.owner, 120, world);
  528.  
  529.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  530.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  531.     WriteCoord (MSG_BROADCAST, self.origin_x);
  532.     WriteCoord (MSG_BROADCAST, self.origin_y);
  533.     WriteCoord (MSG_BROADCAST, self.origin_z);
  534.  
  535.     BecomeExplosion ();
  536. };
  537.  
  538. void() GrenadeTouch =
  539. {
  540.     if (other == self.owner)
  541.         return;        // don't explode on owner
  542.     if (other.takedamage == DAMAGE_AIM)
  543.     {
  544.         //PATCH****************
  545.         //GrenadeExplode(); commented out and replaced by below
  546.         NewGrenadeExplode();
  547.         //ENDPATCH*************
  548.         return;
  549.     }
  550.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  551.     if (self.velocity == '0 0 0')
  552.         self.avelocity = '0 0 0';
  553. };
  554.  
  555. /*
  556. ================
  557. W_FireGrenade
  558. ================
  559. */
  560. void() W_FireGrenade =
  561. {
  562.     local    entity missile, mpuff;
  563.     
  564.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  565.     
  566.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  567.  
  568.     self.punchangle_x = -2;
  569.  
  570.     missile = spawn ();
  571.     missile.owner = self;
  572.     missile.movetype = MOVETYPE_BOUNCE;
  573.     missile.solid = SOLID_BBOX;
  574.     missile.classname = "grenade";
  575.         
  576. // set missile speed    
  577.  
  578.     makevectors (self.v_angle);
  579.  
  580.     if (self.v_angle_x)
  581.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  582.     else
  583.     {
  584.         missile.velocity = aim(self, 10000);
  585.         missile.velocity = missile.velocity * 600;
  586.         missile.velocity_z = 200;
  587.     }
  588.  
  589.     missile.avelocity = '300 300 300';
  590.  
  591.     missile.angles = vectoangles(missile.velocity);
  592.     
  593.     missile.touch = GrenadeTouch;
  594.     
  595. // set missile duration
  596.     missile.nextthink = time + 2.5;
  597.     //PATCH***************************
  598.     //missile.think = GrenadeExplode;
  599.     missile.think = NewGrenadeExplode;
  600.     //ENDPATCH************************
  601.  
  602.     setmodel (missile, "progs/grenade.mdl");
  603.     setsize (missile, '0 0 0', '0 0 0');        
  604.     setorigin (missile, self.origin);
  605. };
  606.  
  607.  
  608. //=============================================================================
  609.  
  610. void() spike_touch;
  611. void() superspike_touch;
  612.  
  613.  
  614. /*
  615. ===============
  616. launch_spike
  617.  
  618. Used for both the player and the ogre
  619. ===============
  620. */
  621. void(vector org, vector dir) launch_spike =
  622. {
  623.     newmis = spawn ();
  624.     newmis.owner = self;
  625.     newmis.movetype = MOVETYPE_FLYMISSILE;
  626.     newmis.solid = SOLID_BBOX;
  627.  
  628.     newmis.angles = vectoangles(dir);
  629.     
  630.     //PATCH****************
  631.     //newmis.touch = spike_touch;
  632.     newmis.touch = new_spike_touch;
  633.     //ENDPATCH*************
  634.     newmis.classname = "spike";
  635.     newmis.think = SUB_Remove;
  636.     newmis.nextthink = time + 6;
  637.     setmodel (newmis, "progs/spike.mdl");
  638.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  639.     setorigin (newmis, org);
  640.  
  641.     newmis.velocity = dir * 1000;
  642. };
  643.  
  644. void() W_FireSuperSpikes =
  645. {
  646.     local vector    dir;
  647.     local entity    old;
  648.     
  649.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  650.     self.attack_finished = time + 0.2;
  651.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  652.     dir = aim (self, 1000);
  653.     launch_spike (self.origin + '0 0 16', dir);
  654.     //PATCH***************************
  655.     //newmis.touch = superspike_touch;
  656.     newmis.touch = new_superspike_touch;
  657.     //ENDPATCH************************
  658.     setmodel (newmis, "progs/s_spike.mdl");
  659.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  660.     self.punchangle_x = -2;
  661. };
  662.  
  663. void(float ox) W_FireSpikes =
  664. {
  665.     local vector    dir;
  666.     local entity    old;
  667.     
  668.     makevectors (self.v_angle);
  669.     
  670.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  671.     {
  672.         W_FireSuperSpikes ();
  673.         return;
  674.     }
  675.  
  676.     if (self.ammo_nails < 1)
  677.     {
  678.         self.weapon = W_BestWeapon ();
  679.         W_SetCurrentAmmo ();
  680.         return;
  681.     }
  682.  
  683.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  684.     self.attack_finished = time + 0.2;
  685.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  686.     dir = aim (self, 1000);
  687.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  688.  
  689.     self.punchangle_x = -2;
  690. };
  691.  
  692.  
  693.  
  694. .float hit_z;
  695. void() spike_touch =
  696. {
  697. local float rand;
  698.     if (other == self.owner)
  699.         return;
  700.  
  701.     if (other.solid == SOLID_TRIGGER)
  702.         return;    // trigger field, do nothing
  703.  
  704.     if (pointcontents(self.origin) == CONTENT_SKY)
  705.     {
  706.         remove(self);
  707.         return;
  708.     }
  709.     
  710. // hit something that bleeds
  711.     if (other.takedamage)
  712.     {
  713.         spawn_touchblood (9);
  714.         T_Damage (other, self, self.owner, 9);
  715.     }
  716.     else
  717.     {
  718.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  719.         
  720.         if (self.classname == "wizspike")
  721.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  722.         else if (self.classname == "knightspike")
  723.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  724.         else
  725.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  726.         WriteCoord (MSG_BROADCAST, self.origin_x);
  727.         WriteCoord (MSG_BROADCAST, self.origin_y);
  728.         WriteCoord (MSG_BROADCAST, self.origin_z);
  729.     }
  730.  
  731.     remove(self);
  732.  
  733. };
  734.  
  735. void() superspike_touch =
  736. {
  737. local float rand;
  738.     if (other == self.owner)
  739.         return;
  740.  
  741.     if (other.solid == SOLID_TRIGGER)
  742.         return;    // trigger field, do nothing
  743.  
  744.     if (pointcontents(self.origin) == CONTENT_SKY)
  745.     {
  746.         remove(self);
  747.         return;
  748.     }
  749.     
  750. // hit something that bleeds
  751.     if (other.takedamage)
  752.     {
  753.         spawn_touchblood (18);
  754.         T_Damage (other, self, self.owner, 18);
  755.     }
  756.     else
  757.     {
  758.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  759.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  760.         WriteCoord (MSG_BROADCAST, self.origin_x);
  761.         WriteCoord (MSG_BROADCAST, self.origin_y);
  762.         WriteCoord (MSG_BROADCAST, self.origin_z);
  763.     }
  764.  
  765.     remove(self);
  766.  
  767. };
  768.  
  769.  
  770. /*
  771. ===============================================================================
  772.  
  773. PLAYER WEAPON USE
  774.  
  775. ===============================================================================
  776. */
  777.  
  778. void() W_SetCurrentAmmo =
  779. {
  780.     player_run ();        // get out of any weapon firing states
  781.  
  782.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  783.     
  784.     if (self.weapon == IT_AXE)
  785.     {
  786.         self.currentammo = 0;
  787.         self.weaponmodel = "progs/v_axe.mdl";
  788.         self.weaponframe = 0;
  789.     }
  790.     else if (self.weapon == IT_SHOTGUN)
  791.     {
  792.         self.currentammo = self.ammo_shells;
  793.         self.weaponmodel = "progs/v_shot.mdl";
  794.         self.weaponframe = 0;
  795.         self.items = self.items | IT_SHELLS;
  796.     }
  797.     else if (self.weapon == IT_SUPER_SHOTGUN)
  798.     {
  799.         self.currentammo = self.ammo_shells;
  800.         self.weaponmodel = "progs/v_shot2.mdl";
  801.         self.weaponframe = 0;
  802.         self.items = self.items | IT_SHELLS;
  803.     }
  804.     else if (self.weapon == IT_NAILGUN)
  805.     {
  806.         self.currentammo = self.ammo_nails;
  807.         self.weaponmodel = "progs/v_nail.mdl";
  808.         self.weaponframe = 0;
  809.         self.items = self.items | IT_NAILS;
  810.     }
  811.     else if (self.weapon == IT_SUPER_NAILGUN)
  812.     {
  813.         self.currentammo = self.ammo_nails;
  814.         self.weaponmodel = "progs/v_nail2.mdl";
  815.         self.weaponframe = 0;
  816.         self.items = self.items | IT_NAILS;
  817.     }
  818.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  819.     {
  820.         self.currentammo = self.ammo_rockets;
  821.         self.weaponmodel = "progs/v_rock.mdl";
  822.         self.weaponframe = 0;
  823.         self.items = self.items | IT_ROCKETS;
  824.     }
  825.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  826.     {
  827.         self.currentammo = self.ammo_rockets;
  828.         self.weaponmodel = "progs/v_rock2.mdl";
  829.         self.weaponframe = 0;
  830.         self.items = self.items | IT_ROCKETS;
  831.     }
  832.     else if (self.weapon == IT_LIGHTNING)
  833.     {
  834.         self.currentammo = self.ammo_cells;
  835.         self.weaponmodel = "progs/v_light.mdl";
  836.         self.weaponframe = 0;
  837.         self.items = self.items | IT_CELLS;
  838.     }
  839.     else
  840.     {
  841.         self.currentammo = 0;
  842.         self.weaponmodel = "";
  843.         self.weaponframe = 0;
  844.     }
  845. };
  846.  
  847. float() W_BestWeapon =
  848. {
  849.     local    float    it;
  850.     
  851.     it = self.items;
  852.  
  853.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  854.         return IT_LIGHTNING;
  855.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  856.         return IT_SUPER_NAILGUN;
  857.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  858.         return IT_SUPER_SHOTGUN;
  859.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  860.         return IT_NAILGUN;
  861.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  862.         return IT_SHOTGUN;
  863.         
  864. /*
  865.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  866.         return IT_ROCKET_LAUNCHER;
  867.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  868.         return IT_GRENADE_LAUNCHER;
  869.  
  870. */
  871.  
  872.     return IT_AXE;
  873. };
  874.  
  875. float() W_CheckNoAmmo =
  876. {
  877.     if (self.currentammo > 0)
  878.         return TRUE;
  879.  
  880.     if (self.weapon == IT_AXE)
  881.         return TRUE;
  882.     
  883.     self.weapon = W_BestWeapon ();
  884.  
  885.     W_SetCurrentAmmo ();
  886.     
  887. // drop the weapon down
  888.     return FALSE;
  889. };
  890.  
  891. /*
  892. ============
  893. W_Attack
  894.  
  895. An attack impulse can be triggered now
  896. ============
  897. */
  898. void()    player_axe1;
  899. void()    player_axeb1;
  900. void()    player_axec1;
  901. void()    player_axed1;
  902. void()    player_shot1;
  903. void()    player_nail1;
  904. void()    player_light1;
  905. void()    player_rocket1;
  906.  
  907. void() W_Attack =
  908. {
  909.     local    float    r;
  910.  
  911.     if (!W_CheckNoAmmo ())
  912.         return;
  913.  
  914.     makevectors    (self.v_angle);            // calculate forward angle for velocity
  915.     self.show_hostile = time + 1;    // wake monsters up
  916.  
  917.     if (self.weapon == IT_AXE)
  918.     {
  919.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  920.         r = random();
  921.         if (r < 0.25)
  922.             player_axe1 ();
  923.         else if (r<0.5)
  924.             player_axeb1 ();
  925.         else if (r<0.75)
  926.             player_axec1 ();
  927.         else
  928.             player_axed1 ();
  929.         self.attack_finished = time + 0.5;
  930.     }
  931.     else if (self.weapon == IT_SHOTGUN)
  932.     {
  933.         player_shot1 ();
  934.         W_FireShotgun ();
  935.         self.attack_finished = time + 0.5;
  936.     }
  937.     else if (self.weapon == IT_SUPER_SHOTGUN)
  938.     {
  939.         player_shot1 ();
  940.         W_FireSuperShotgun ();
  941.         self.attack_finished = time + 0.7;
  942.     }
  943.     else if (self.weapon == IT_NAILGUN)
  944.     {
  945.         player_nail1 ();
  946.     }
  947.     else if (self.weapon == IT_SUPER_NAILGUN)
  948.     {
  949.         player_nail1 ();
  950.     }
  951.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  952.     {
  953.         player_rocket1();
  954.         W_FireGrenade();
  955.         self.attack_finished = time + 0.6;
  956.     }
  957.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  958.     {
  959.         player_rocket1();
  960.         W_FireRocket();
  961.         self.attack_finished = time + 0.8;
  962.     }
  963.     else if (self.weapon == IT_LIGHTNING)
  964.     {
  965.         player_light1();
  966.         self.attack_finished = time + 0.1;
  967.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  968.     }
  969. };
  970.  
  971. /*
  972. ============
  973. W_ChangeWeapon
  974.  
  975. ============
  976. */
  977. void() W_ChangeWeapon =
  978. {
  979.     local    float    it, am, fl;
  980.     
  981.     it = self.items;
  982.     am = 0;
  983.     
  984.     if (self.impulse == 1)
  985.     {
  986.         fl = IT_AXE;
  987.     }
  988.     else if (self.impulse == 2)
  989.     {
  990.         fl = IT_SHOTGUN;
  991.         if (self.ammo_shells < 1)
  992.             am = 1;
  993.     }
  994.     else if (self.impulse == 3)
  995.     {
  996.         fl = IT_SUPER_SHOTGUN;
  997.         if (self.ammo_shells < 2)
  998.             am = 1;
  999.     }        
  1000.     else if (self.impulse == 4)
  1001.     {
  1002.         fl = IT_NAILGUN;
  1003.         if (self.ammo_nails < 1)
  1004.             am = 1;
  1005.     }
  1006.     else if (self.impulse == 5)
  1007.     {
  1008.         fl = IT_SUPER_NAILGUN;
  1009.         if (self.ammo_nails < 2)
  1010.             am = 1;
  1011.     }
  1012.     else if (self.impulse == 6)
  1013.     {
  1014.         fl = IT_GRENADE_LAUNCHER;
  1015.         if (self.ammo_rockets < 1)
  1016.             am = 1;
  1017.     }
  1018.     else if (self.impulse == 7)
  1019.     {
  1020.         fl = IT_ROCKET_LAUNCHER;
  1021.         if (self.ammo_rockets < 1)
  1022.             am = 1;
  1023.     }
  1024.     else if (self.impulse == 8)
  1025.     {
  1026.         fl = IT_LIGHTNING;
  1027.         if (self.ammo_cells < 1)
  1028.             am = 1;
  1029.     }
  1030.  
  1031.     self.impulse = 0;
  1032.     
  1033.     if (!(self.items & fl))
  1034.     {    // don't have the weapon or the ammo
  1035.         sprint (self, "no weapon.\n");
  1036.         return;
  1037.     }
  1038.     
  1039.     if (am)
  1040.     {    // don't have the ammo
  1041.         sprint (self, "not enough ammo.\n");
  1042.         return;
  1043.     }
  1044.  
  1045. //
  1046. // set weapon, set ammo
  1047. //
  1048.     self.weapon = fl;        
  1049.     W_SetCurrentAmmo ();
  1050. };
  1051.  
  1052. /*
  1053. ============
  1054. CheatCommand
  1055. ============
  1056. */
  1057. void() CheatCommand =
  1058. {
  1059.     if (deathmatch || coop)
  1060.         return;
  1061.  
  1062.     self.ammo_rockets = 100;
  1063.     self.ammo_nails = 200;
  1064.     self.ammo_shells = 100;
  1065.     self.items = self.items | 
  1066.         IT_AXE |
  1067.         IT_SHOTGUN |
  1068.         IT_SUPER_SHOTGUN |
  1069.         IT_NAILGUN |
  1070.         IT_SUPER_NAILGUN |
  1071.         IT_GRENADE_LAUNCHER |
  1072.         IT_ROCKET_LAUNCHER |
  1073.         IT_KEY1 | IT_KEY2;
  1074.  
  1075.     self.ammo_cells = 200;
  1076.     self.items = self.items | IT_LIGHTNING;
  1077.  
  1078.     self.weapon = IT_ROCKET_LAUNCHER;
  1079.     self.impulse = 0;
  1080.     W_SetCurrentAmmo ();
  1081. };
  1082.  
  1083. /*
  1084. ============
  1085. CycleWeaponCommand
  1086.  
  1087. Go to the next weapon with ammo
  1088. ============
  1089. */
  1090. void() CycleWeaponCommand =
  1091. {
  1092.     local    float    it, am;
  1093.     
  1094.     it = self.items;
  1095.     self.impulse = 0;
  1096.     
  1097.     while (1)
  1098.     {
  1099.         am = 0;
  1100.  
  1101.         if (self.weapon == IT_LIGHTNING)
  1102.         {
  1103.             self.weapon = IT_AXE;
  1104.         }
  1105.         else if (self.weapon == IT_AXE)
  1106.         {
  1107.             self.weapon = IT_SHOTGUN;
  1108.             if (self.ammo_shells < 1)
  1109.                 am = 1;
  1110.         }
  1111.         else if (self.weapon == IT_SHOTGUN)
  1112.         {
  1113.             self.weapon = IT_SUPER_SHOTGUN;
  1114.             if (self.ammo_shells < 2)
  1115.                 am = 1;
  1116.         }        
  1117.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1118.         {
  1119.             self.weapon = IT_NAILGUN;
  1120.             if (self.ammo_nails < 1)
  1121.                 am = 1;
  1122.         }
  1123.         else if (self.weapon == IT_NAILGUN)
  1124.         {
  1125.             self.weapon = IT_SUPER_NAILGUN;
  1126.             if (self.ammo_nails < 2)
  1127.                 am = 1;
  1128.         }
  1129.         else if (self.weapon == IT_SUPER_NAILGUN)
  1130.         {
  1131.             self.weapon = IT_GRENADE_LAUNCHER;
  1132.             if (self.ammo_rockets < 1)
  1133.                 am = 1;
  1134.         }
  1135.         else if (self.weapon == IT_GRENADE_LAUNCHER)
  1136.         {
  1137.             self.weapon = IT_ROCKET_LAUNCHER;
  1138.             if (self.ammo_rockets < 1)
  1139.                 am = 1;
  1140.         }
  1141.         else if (self.weapon == IT_ROCKET_LAUNCHER)
  1142.         {
  1143.             self.weapon = IT_LIGHTNING;
  1144.             if (self.ammo_cells < 1)
  1145.                 am = 1;
  1146.         }
  1147.     
  1148.         if ( (self.items & self.weapon) && am == 0)
  1149.         {
  1150.             W_SetCurrentAmmo ();
  1151.             return;
  1152.         }
  1153.     }
  1154.  
  1155. };
  1156.  
  1157. /*
  1158. ============
  1159. ServerflagsCommand
  1160.  
  1161. Just for development
  1162. ============
  1163. */
  1164. void() ServerflagsCommand =
  1165. {
  1166.     serverflags = serverflags * 2 + 1;
  1167. };
  1168.  
  1169. void() QuadCheat =
  1170. {
  1171.     if (deathmatch || coop)
  1172.         return;
  1173.     self.super_time = 1;
  1174.     self.super_damage_finished = time + 30;
  1175.     self.items = self.items | IT_QUAD;
  1176.     dprint ("quad cheat\n");
  1177. };
  1178.  
  1179. /*
  1180. ============
  1181. ImpulseCommands
  1182.  
  1183. ============
  1184. */
  1185. void() ImpulseCommands =
  1186. {
  1187.     if (self.impulse >= 1 && self.impulse <= 8)
  1188.         W_ChangeWeapon ();
  1189.  
  1190.     if (self.impulse == 9)
  1191.         CheatCommand ();
  1192.     if (self.impulse == 10)
  1193.         CycleWeaponCommand ();
  1194.     if (self.impulse == 11)
  1195.         ServerflagsCommand ();
  1196.  
  1197.     if (self.impulse == 255)
  1198.         QuadCheat ();
  1199.         
  1200.     self.impulse = 0;
  1201. };
  1202.  
  1203. /*
  1204. ============
  1205. W_WeaponFrame
  1206.  
  1207. Called every frame so impulse events can be handled as well as possible
  1208. ============
  1209. */
  1210. void() W_WeaponFrame =
  1211. {
  1212.     if (time < self.attack_finished)
  1213.         return;
  1214.  
  1215.     ImpulseCommands ();
  1216.     
  1217. // check for attack
  1218.     if (self.button0)
  1219.     {
  1220.         SuperDamageSound ();
  1221.         W_Attack ();
  1222.     }
  1223. };
  1224.  
  1225. /*
  1226. ========
  1227. SuperDamageSound
  1228.  
  1229. Plays sound if needed
  1230. ========
  1231. */
  1232. void() SuperDamageSound =
  1233. {
  1234.     if (self.super_damage_finished > time)
  1235.     {
  1236.         if (self.super_sound < time)
  1237.         {
  1238.             self.super_sound = time + 1;
  1239.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  1240.         }
  1241.     }
  1242.     return;
  1243. };
  1244.  
  1245.  
  1246.